/*

Copyright (c) 2004-2009 Krzysztof Ostrowski. All rights reserved.

Redistribution and use in source and binary forms,
with or without modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above
   copyright notice, this list of conditions and the following
   disclaimer in the documentation and/or other materials provided
   with the distribution.

THIS SOFTWARE IS PROVIDED "AS IS" BY THE ABOVE COPYRIGHT HOLDER(S)
AND ALL OTHER CONTRIBUTORS AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDER(S) OR ANY OTHER
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

*/

using System;
using System.Collections.Generic;
using System.Text;

namespace QS._qss_x_.Language_.Compiler_
{
    public static class Template
    {
		public const string TEMPLATE = 
@"
// Generated by the QuickSilver Properties Framework

// #define DEBUG_LogGenerously
// #define DEBUG_LogGenerously_2
// #define DEBUG_LogPropertyValueAssignments
// #define DEBUG_MonotonicChecks
// #define DEBUG_SetAcknowledgement
#define DEBUG_DisseminateDecisionsWithoutMerging
#define OPTION_RejectDisseminatedParentValuesFromOldCofigurationIncarnations

using System;
using System.Collections.Generic;
using System.Text;
using QS.Fx.Runtime;
using QS.Fx.Runtime2;

namespace QS.Fx.Protocols.Generated
{
    public sealed class PROTOCOL : QS.Fx.Agents.Base.IProtocol
    {
        #region Plumbing

        #region Constructors

        public static QS.Fx.Agents.Base.IProtocol Protocol
        {
            get { return _protocol; }
        }

        private static readonly PROTOCOL _protocol = new PROTOCOL();

        private PROTOCOL()
        {
        }

        #endregion Constructors

        #region Constants

        private static uint MaximumNumberOfRangesForNetworkCommunication = 100;

        #endregion Constants

        #region QS.Fx.Agents.Base.IProtocol Members

        string QS.Fx.Agents.Base.IProtocol.Name
        {
            get { return ""PROTOCOL""; }
        }

        Type QS.Fx.Agents.Base.IProtocol.Interface
        {
            get { return typeof(IEndpoint); }
        }

        QS.Fx.Agents.Base.IProtocolRoot QS.Fx.Agents.Base.IProtocol.Root()
        {
            return new Root();
        }

        QS.Fx.Agents.Base.IProtocolPeer QS.Fx.Agents.Base.IProtocol.Peer(QS.Fx.Agents.Base.IProtocolPeerContext peercontext)
        {
            return new Peer(peercontext);
        }

        QS.Fx.Agents.Base.IProtocolBind QS.Fx.Agents.Base.IProtocol.Bind(object endpoint)
        {
            System.Diagnostics.Debug.Assert((endpoint != null) && typeof(IEndpoint).IsAssignableFrom(endpoint.GetType()));
            return new Bind((IEndpoint)endpoint);
        }

        #endregion QS.Fx.Agents.Base.IProtocol Members

        #endregion

        #region Interface IEndpoint

        // CALLBACK_DECLARATIONS

        public interface IEndpoint
        {
            // INTERFACE
        }

        #endregion Interface IEndpoint

        #region Logic

        #region Class Control

        [QS.Fx.Printing.Printable(QS.Fx.Printing.PrintingStyle.Expanded, QS.Fx.Printing.SelectionOption.Explicit)]
        private abstract class Control : QS.TMS.Inspection.Inspectable, QS.Fx.Agents.Base.IProtocolControl
        {
            #region Constructor

            public Control()
            {
            }

            #endregion Constructor

            #region Fields

            [QS.TMS.Inspection.Inspectable]
            public Control uppercontrol, lowercontrol;
            [QS.TMS.Inspection.Inspectable]
            public QS.Fx.Logging.ILogger logger;
            // CONTROL_ADDITIONAL_FIELDS

            #endregion Fields

            #region IProtocolControl.Initialize

            void QS.Fx.Agents.Base.IProtocolControl.Initialize(QS.Fx.Logging.ILogger logger)
            {
                lock (this)
                {
                    this.logger = logger;
                    _Initialization();
                }
            }

            #endregion

            #region IProtocolControl.ConnectUpper

            void QS.Fx.Agents.Base.IProtocolControl.ConnectUpper(QS.Fx.Agents.Base.IProtocolControl control)
            {
                lock (this)
                {
                    uppercontrol = (Control)control;
                    _UpdatedUpper();
                }
            }

            #endregion

            #region IProtocolControl.ConnectLower

            void QS.Fx.Agents.Base.IProtocolControl.ConnectLower(QS.Fx.Agents.Base.IProtocolControl control)
            {
                lock (this)
                {
                    lowercontrol = (Control)control;
                    _UpdatedLower();
                }
            }

            #endregion

            #region _Initialization

            public virtual void _Initialization()
            {
            }

            #endregion

            #region _UpdatedLower

            public virtual void _UpdatedLower()
            {
            }

            #endregion

            #region _UpdatedUpper

            public virtual void _UpdatedUpper()
            {
            }

            #endregion
        }

        #endregion Class Control

        #region Class Bind

        [QS.Fx.Printing.Printable(QS.Fx.Printing.PrintingStyle.Expanded, QS.Fx.Printing.SelectionOption.Explicit)]
        private sealed class Bind : Control, QS.Fx.Agents.Base.IProtocolBind
        {
            #region Constructor

            public Bind(IEndpoint endpoint) : base()
            {
                lock (this)
                {
                    this.endpoint = endpoint;
                }
            }

            #endregion

            #region Fields

            [QS.TMS.Inspection.Inspectable]
            public IEndpoint endpoint;
            // BIND_ADDITIONAL_FIELDS

            #endregion

            #region _Initialization

            public override void _Initialization()
            {
                lock (this)
                {
                    // BIND_INITIALIZATION
                    // BIND_REGISTER_CALLBACKS
                }
            }

            #endregion

            #region _UpdatedLower

            public override void _UpdatedLower()
            {
                System.Diagnostics.Debug.Assert(false);
            }

            #endregion

            #region _UpdatedUpper

            public override void _UpdatedUpper()
            {
                // BIND_UPDATED_UPPER
            }

            #endregion

            // BIND_CALLBACKS
        }

        #endregion Class Bind

        #region Class Peer

        [QS.Fx.Printing.Printable(QS.Fx.Printing.PrintingStyle.Expanded, QS.Fx.Printing.SelectionOption.Explicit)]
        private sealed class Peer : Control, QS.Fx.Agents.Base.IProtocolPeer, QS.Fx.Agents.Base.IProtocolControl
        {
            #region Constructor

            public Peer(QS.Fx.Agents.Base.IProtocolPeerContext peercontext) : base()
            {
                this.peercontext = peercontext;
            }

            #endregion

            #region Fields

            [QS.TMS.Inspection.Inspectable]
            public bool updatedupper1, updatedupper2;
            [QS.TMS.Inspection.Inspectable]
            public QS.Fx.Agents.Base.IProtocolPeerContext peercontext;
            // PEER_ADDITIONAL_FIELDS

            #endregion

            #region IProtocolControl.Initialize

            void QS.Fx.Agents.Base.IProtocolControl.Initialize(QS.Fx.Logging.ILogger logger)
            {
                this.logger = logger;
                logger.Log(""This peer agent is starting as "" + (peercontext.IsRegular ? ""a normal"" : ""an associate"") + "" member of the peer group."");
                _Initialization();
            }

            #endregion

            #region _Initialization

            public override void _Initialization()
            {
                lock (this)
                {
                    // PEER_INITIALIZATION
                }
            }

            #endregion

            #region _UpdatedLower

            public override void _UpdatedLower()
            {
                if (lowercontrol is Bind)
                {
                    // PEER_UPDATED_LOWER_BIND
                }
                else
                {
                    System.Diagnostics.Debug.Assert(lowercontrol is Peer);
                    // PEER_UPDATED_LOWER_PEER
                }
            }

            #endregion

            #region _UpdatedUpper

            public override void _UpdatedUpper()
            {
                updatedupper1 = true;
            }

            #endregion

            #region _UpperConsume1

            private void _UpperConsume1(QS.Fx.Runtime.Version version)
            {
#if DEBUG_LogGenerously_2
                logger.Log(""_UpperConsume1 : version = "" + version.ToString());
#endif

                if (updatedupper1)
                {
#if DEBUG_LogGenerously
                    logger.Log(""_UpperConsume1("" + version.ToString() + "") : Updating from Upper"");
#endif

                    updatedupper1 = false;

                    if (uppercontrol != null)
                    {
                        // PEER_UPPER_CONSUME_1

                        updatedupper2 = true;
                    }
                }
            }

            #endregion

            #region _UpperConsume2

            private void _UpperConsume2
            (
                // PEER_UPPER_CONSUME_2_PARAMETERS                
            )
            {
#if DEBUG_LogGenerously_2
                logger.Log(""_UpperConsume2"");
#endif

                // PEER_UPPER_CONSUME_2
            }

            #endregion

            #region _UpperConsume3

            private void _UpperConsume3(QS.Fx.Runtime.Version version)
            {
#if DEBUG_LogGenerously_2
                logger.Log(""_UpperConsume3"");
#endif

                if (updatedupper2)
                {
#if DEBUG_LogGenerously
                    logger.Log(""_UpperConsume3 : Updating this"");
#endif

                    updatedupper2 = false;

                    // PEER_UPPER_CONSUME_3

                    if (lowercontrol != null)
                        lowercontrol._UpdatedUpper();
                }
            }

            #endregion

            #region _CheckConditions

            private void _CheckConditions()
            {
                // CHECK_CONDITIONS
            }

            #endregion

            #region _Upgrade

            private void _Upgrade()
            {
                if (!peercontext.IsRegular)
                {
                    logger.Log(""UPDATING TO REGULAR"");
                    peercontext.IsRegular = true;
                    // System.Diagnostics.Debug.Assert(false, ""Not Implemented : Upgrading Associate to Regular"");
                }
            }

            #endregion

            #region _Degrade

            private void _Degrade()
            {
                if (peercontext.IsRegular)
                {
                    logger.Log(""DEGRADING TO ASSOCIATE"");
                    peercontext.IsRegular = false;
                    // System.Diagnostics.Debug.Assert(false, ""Not Implemented: Degrading Regular to Associate"");
                }
            }

            #endregion

            #region IProtocolPeer.Aggregate (1)

            bool QS.Fx.Agents.Base.IProtocolPeer.Aggregate(QS.Fx.Runtime.Version version, out QS.Fx.Serialization.ISerializable _outgoing)
            {
#if DEBUG_LogGenerously_2
                logger.Log(""Aggregate_1 : version = "" + version.ToString());
#endif

                lock (this)
                {
                    AggregationToken outgoing = new AggregationToken();
                    _outgoing = outgoing;

                    _UpperConsume1(version);
                    _UpperConsume3(version);

                    // PEER_AGGREGATE_1
                }

                return true;
            }

            #endregion

            #region IProtocolPeer.Aggregate (2)

            bool QS.Fx.Agents.Base.IProtocolPeer.Aggregate(QS.Fx.Runtime.Version version,
                QS.Fx.Serialization.ISerializable _incoming, out QS.Fx.Serialization.ISerializable _outgoing)
            {
#if DEBUG_LogGenerously_2
                logger.Log(""Aggregate_2 : version = "" + version.ToString());
#endif

                lock (this)
                {
                    AggregationToken incoming = (AggregationToken) _incoming;

                    if (incoming == null)
                    {
                        _outgoing = null;
                        return false;
                    }

                    _UpperConsume1(version);
                    _UpperConsume2
                    (
                        version, 
                        // PEER_UPPER_CONSUME_2_ARGUMENTS
                    );
                    _UpperConsume3(version);

                    AggregationToken outgoing = new AggregationToken();
                    _outgoing = outgoing;

                    // PEER_AGGREGATE_2
                }

                return true;
            }

            #endregion

            #region IProtocolPeer.Aggregate (3)

            bool QS.Fx.Agents.Base.IProtocolPeer.Aggregate(QS.Fx.Runtime.Version version, QS.Fx.Serialization.ISerializable _incoming)
            {
#if DEBUG_LogGenerously_2
                logger.Log(""Aggregate_3 : version = "" + version.ToString());
#endif

                lock (this)
                {
                    AggregationToken incoming = (AggregationToken)_incoming;

                    if (incoming == null)
                        return false;

                    _UpperConsume1(version);
                    _UpperConsume2
                    (
                        version, 
                        // PEER_UPPER_CONSUME_2_ARGUMENTS
                    );
                    _UpperConsume3(version);

                    // PEER_AGGREGATE_3

                    if (uppercontrol != null)
                        uppercontrol._UpdatedLower();
                }

                return true;
            }

            #endregion

            #region IProtocolPeer.Disseminate (1)

            bool QS.Fx.Agents.Base.IProtocolPeer.Disseminate(QS.Fx.Runtime.Version version, out QS.Fx.Serialization.ISerializable _outgoing)
            {
#if DEBUG_LogGenerously_2
                logger.Log(""Disseminate_1 : version = "" + version.ToString());
#endif

                lock (this)
                {
                    DisseminationToken outgoing = new DisseminationToken();
                    _outgoing = outgoing;

                    // PEER_DISSEMINATE_1

                    _CheckConditions();
                }

                return true;
            }

            #endregion

            #region IProtocolPeer.Disseminate (2)

            bool QS.Fx.Agents.Base.IProtocolPeer.Disseminate(QS.Fx.Runtime.Version version,
                QS.Fx.Serialization.ISerializable _incoming, out QS.Fx.Serialization.ISerializable _outgoing)
            {
#if DEBUG_LogGenerously_2
                logger.Log(""Disseminate_2 : version = "" + version.ToString());
#endif

                lock (this)
                {
                    DisseminationToken incoming = (DisseminationToken) _incoming;

                    if (incoming == null)
                    {
                        _outgoing = null;
                        return false;
                    }

                    // PEER_DISSEMINATE_2_AND_3
                    _UpperConsume2
                    (
                        version, 
                        // PEER_UPPER_CONSUME_2_ARGUMENTS
                    );
                    _UpperConsume3(version);

                    DisseminationToken outgoing = incoming;
                    _outgoing = outgoing;

                    if (uppercontrol != null)
                        uppercontrol._UpdatedLower();

                    _CheckConditions();
                }

                return true;
            }

            #endregion

            #region IProtocolPeer.Disseminate (3)

            bool QS.Fx.Agents.Base.IProtocolPeer.Disseminate(QS.Fx.Runtime.Version version, QS.Fx.Serialization.ISerializable _incoming)
            {
#if DEBUG_LogGenerously_2
                logger.Log(""Disseminate_3 : version = "" + version.ToString());
#endif

                lock (this)
                {
                    DisseminationToken incoming = (DisseminationToken) _incoming;

                    if (incoming == null)
                        return false;

                    // PEER_DISSEMINATE_2_AND_3
                    _UpperConsume2
                    (
                        version, 
                        // PEER_UPPER_CONSUME_2_ARGUMENTS
                    );
                    _UpperConsume3(version);

                    if (uppercontrol != null)
                        uppercontrol._UpdatedLower();

                    _CheckConditions();
                }

                return true;
            }

            #endregion
        }

        #endregion Class Peer

        #region Class Root

        [QS.Fx.Printing.Printable(QS.Fx.Printing.PrintingStyle.Expanded, QS.Fx.Printing.SelectionOption.Explicit)]
        private sealed class Root : Control, QS.Fx.Agents.Base.IProtocolRoot
        {
            #region Constructor

            public Root() : base()
            {
            }

            #endregion

            #region Fields

            // ROOT_ADDITIONAL_FIELDS

            #endregion

            #region _Initialization

            public override void _Initialization()
            {
                lock (this)
                {
                    // ROOT_INITIALIZATION
                }
            }

            #endregion

            #region _UpdatedLower

            public override void _UpdatedLower()
            {
                System.Diagnostics.Debug.Assert(lowercontrol is Peer);

                // ROOT_UPDATED_LOWER

                if (lowercontrol != null)
                    lowercontrol._UpdatedUpper();
            }

            #endregion

            #region _UpdatedUpper

            public override void _UpdatedUpper()
            {
                System.Diagnostics.Debug.Assert(false);
            }

            #endregion
        }

        #endregion Class Root

        #endregion Logic

        #region Tokens

        #region Class AggregationToken

        [QS.Fx.Printing.Printable(QS.Fx.Printing.PrintingStyle.Expanded, QS.Fx.Printing.SelectionOption.Explicit)]
        [QS.Fx.Serialization.ClassID(QS.ClassID.Fx_Protocols_Generated_AggregationToken)]
        public sealed class AggregationToken : QS.Fx.Serialization.ISerializable
        {
            #region Constructor

            public AggregationToken()
            {
            }

            #endregion

            #region Fields

            // AGGREGATIONTOKEN_FIELDS

            #endregion

            #region ISerializable Members

            QS.Fx.Serialization.SerializableInfo QS.Fx.Serialization.ISerializable.SerializableInfo
            {
                get
                {
                    QS.Fx.Serialization.SerializableInfo info = new QS.Fx.Serialization.SerializableInfo(QS.ClassID.Fx_Protocols_Generated_AggregationToken);
                    // AGGREGATIONTOKEN_SERIALIZABLEINFO
                    return info;
                }
            }

            void QS.Fx.Serialization.ISerializable.SerializeTo(ref QS.Fx.Base.ConsumableBlock header, ref IList<QS.Fx.Base.Block> data)
            {
                // AGGREGATIONTOKEN_SERIALIZETO
            }

            void QS.Fx.Serialization.ISerializable.DeserializeFrom(ref QS.Fx.Base.ConsumableBlock header, ref QS.Fx.Base.ConsumableBlock data)
            {
                // AGGREGATIONTOKEN_DESERIALIZEFROM
            }

            #endregion
        }

        #endregion Class AggregationToken

        #region Class DisseminationToken

        [QS.Fx.Printing.Printable(QS.Fx.Printing.PrintingStyle.Expanded, QS.Fx.Printing.SelectionOption.Explicit)]
        [QS.Fx.Serialization.ClassID(QS.ClassID.Fx_Protocols_Generated_DisseminationToken)]
        public sealed class DisseminationToken : QS.Fx.Serialization.ISerializable
        {
            #region Constructor

            public DisseminationToken()
            {
            }

            #endregion

            #region Fields

            // DISSEMINATIONTOKEN_FIELDS

            #endregion

            #region ISerializable Members

            QS.Fx.Serialization.SerializableInfo QS.Fx.Serialization.ISerializable.SerializableInfo
            {
                get
                {
                    QS.Fx.Serialization.SerializableInfo info = new QS.Fx.Serialization.SerializableInfo(QS.ClassID.Fx_Protocols_Generated_DisseminationToken);
                    // DISSEMINATIONTOKEN_SERIALIZABLEINFO
                    return info;
                }
            }

            void QS.Fx.Serialization.ISerializable.SerializeTo(ref QS.Fx.Base.ConsumableBlock header, ref IList<QS.Fx.Base.Block> data)
            {
                // DISSEMINATIONTOKEN_SERIALIZETO
            }

            void QS.Fx.Serialization.ISerializable.DeserializeFrom(ref QS.Fx.Base.ConsumableBlock header, ref QS.Fx.Base.ConsumableBlock data)
            {
                // DISSEMINATIONTOKEN_DESERIALIZEFROM
            }

            #endregion
        }

        #endregion Class DisseminationToken

        #endregion Tokens
    }
}
";
    }
}
